package com.cpit.platform.tool.util;

import com.cpit.platform.common.excel.annotation.ExcelField;
import com.cpit.platform.tool.entity.FieldInfo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.persistence.Column;
import java.io.*;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;


public class FileGenerator {
    private Logger logger = LoggerFactory.getLogger(FileGenerator.class);

    private static String packageNameTitle ="分类".toLowerCase();
    private static  String modelNameTitle = "名称".toLowerCase();
    private static  String fieldChineseNameTitle = "属性".toLowerCase();
    private static  String fieldEnglishNameTitle ="EnglishName".toLowerCase();
    private static  String typeTitle = 	"Type".toLowerCase();
    private static  String lengthTitle = "Length".toLowerCase();
    private static  String nullableTitle = "Nullable".toLowerCase();
    private static  String dataFormatTitle = "DataFormat".toLowerCase();
    private static  String enumValueTitle = "EnumValue".toLowerCase();
    private static  String uniqueTitle = "Unique".toLowerCase();
    private  static Workbook getWorkbook(String filepath){
        Workbook wb = null;
        try {
            int pos = filepath.lastIndexOf(".");
            if(pos == -1){
                System.out.println("[In getWorkbook]File has no ext, filepath ="+filepath);
            }else{
                String ext = filepath.substring(pos);
                InputStream is = new FileInputStream(filepath);
                if(".xls".equals(ext)){
                    wb = new HSSFWorkbook(is);
                }else if(".xlsx".equals(ext)){
                    wb = new XSSFWorkbook(is);
                }else{
                    wb=null;
                    System.out.println("[In getWorkbook]file name does'nt contain  .xls or .xlsx,filepath="+filepath);
                }
            }
        } catch (Exception e) {
            System.out.println("[In getWorkbook]catch (Exception e), filepath ="+filepath);
            e.printStackTrace();
        }
        return  wb;
    }
    public  static  Map<String,Map<String,List<FieldInfo>>> readData(String filepath) throws Exception{
        return  readData(filepath,true);
    }
    private   static  Map<String,Map<String,List<FieldInfo>>> readData(String filepath,boolean vertical) throws Exception{
        Map<String,Integer[]> title2RowColumnMap = new HashMap<>() ;
        String[] titles = {packageNameTitle,modelNameTitle,fieldChineseNameTitle,fieldEnglishNameTitle,typeTitle,lengthTitle	,nullableTitle,dataFormatTitle,enumValueTitle,uniqueTitle};
        for(String title:titles){
            title2RowColumnMap.put(title,new Integer[2]);
        }
        Map<String,Map<String,List<FieldInfo>>>  allMap = new HashMap<>();
        File file = new File(filepath);
        if(file.exists()){
            if(file.isDirectory()){
                //处理多个文件
                File[] fileNames = file.listFiles();
                for(File tmpFile:fileNames){
                    try{
                        processorFile(tmpFile.getAbsolutePath(),vertical,allMap,title2RowColumnMap);
                    } catch (Exception e) {
                        System.out.println("process filepath catch Exception,filepath = "+tmpFile.getAbsolutePath());
                        e.printStackTrace();
                    }
                }
            }else{
                try {
                    processorFile(filepath,vertical,allMap,title2RowColumnMap);
                } catch (Exception e) {
                    System.out.println("process filepath catch Exception,filepath = "+filepath);
                    e.printStackTrace();
                }
            }
        }else{
            System.out.println("filepath does'nt exist. filepath = "+filepath);
        }
        return allMap;
    }

    private  static void processorFile(String filepath,boolean vertical,Map<String,Map<String,List<FieldInfo>>>  allMap,Map<String,Integer[]> title2RowColumnMap  ) throws Exception{
        Workbook wb = getWorkbook(filepath);
        if(wb==null){
            throw new Exception( "Workbook对象为空,filepath = "+ filepath);
        }
        int numberOfSheets = wb.getNumberOfSheets();
        for(int i = 0; i < numberOfSheets; i++){
            processOneSheet(filepath,wb,vertical,allMap,title2RowColumnMap,i);
        }
    }

    private static  void processOneSheet(String filepath,Workbook wb,boolean vertical,Map<String,Map<String,List<FieldInfo>>> allMap,Map<String,Integer[]> title2RowColumnMap,int sheetIndex){
        //第一个sheet的数据
        Sheet sheet = wb.getSheetAt(sheetIndex);
        int rowNum = sheet.getLastRowNum();
        if (rowNum < 2){
            return;
        }
        Row row =  sheet.getRow(0);
        int colNum = row.getPhysicalNumberOfCells();
        if (colNum < 4){
            return;
        }
        //针对每一个sheet，重新查找Title定义位置
        for (int r = 0; r <= rowNum; r++) {
            Row findRow = sheet.getRow(r);
            for (int c = 0 ;c < colNum; c++) {
                Object obj = getCellFormatValue(findRow.getCell(c));
                if ( obj != null){
                    String tmpTitle = purify("title",obj).toLowerCase();
                    Integer[] rc = title2RowColumnMap.get(tmpTitle);
                    if(rc != null){
                        rc[0] = r;rc[1] = c;
                    }
                }
            }
        }
        //遍历所有行
        int startRow = title2RowColumnMap.get(title2RowColumnMap.keySet().toArray()[0])[0];
        List<FieldInfo> oneEntityFieldInfoList =  null;
        Map<String,List<FieldInfo>> onePackageEntityMap = null;
        for (int r = startRow + 1; r <= rowNum; r++) {
            try{
                row = sheet.getRow(r);
                String wholePackageName = purify("wholePackageName", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(packageNameTitle))[1])));
                String wholeEntityName =  purify("wholeEntityName", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(modelNameTitle))[1])));
                String fieldChineseName =  purify("fieldChineseName", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(fieldChineseNameTitle))[1])));
                String fieldEnglishName =  purify("fieldEnglishName", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(fieldEnglishNameTitle))[1])));
                String fieldType =  purify("fieldType", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(typeTitle))[1])));
                String fieldLength =  purify("fieldLength", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(lengthTitle))[1])));
                String fieldNullable =  purify("fieldNullable", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(nullableTitle))[1])));
                String fieldDataFormat =  purify("fieldDataFormat", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(dataFormatTitle))[1])));
                String fieldEnumValue =  purify("fieldEnumValue", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(enumValueTitle))[1])));
                String fieldUnique =  purify("fieldUnique", getCellFormatValue(row.getCell((Integer) (title2RowColumnMap.get(uniqueTitle))[1])));
                //new package is not null, mean a new start
                if(wholePackageName != null && wholePackageName.length() > 0){
                    onePackageEntityMap = allMap.get(wholePackageName);
                    if (onePackageEntityMap == null){
                        onePackageEntityMap =  new HashMap<>();
                        allMap.put(wholePackageName,onePackageEntityMap);
                    }
                }
                if(wholeEntityName != null && wholeEntityName.length() > 0){
                    oneEntityFieldInfoList = onePackageEntityMap.get(wholeEntityName);
                    //model name not null, a new model start,record old,begin new one
                    if(oneEntityFieldInfoList == null){
                        oneEntityFieldInfoList = new ArrayList<>();
                        onePackageEntityMap.put( wholeEntityName,oneEntityFieldInfoList);
                    }
                }
                if(!StringUtils.isEmpty(fieldEnglishName)){    //field
                    try{
                        FieldInfo fi = new FieldInfo();
                        fi.setChineseName(StringUtils.isEmpty(fieldChineseName) ? "chinese_name":fieldChineseName);
                        fi.setEnglishName(fieldEnglishName);
                        fi.setType(StringUtils.isEmpty(fieldType) ? "String":fieldType);
                        fi.setLength(StringUtils.isEmpty(fieldLength) ? "255":""+Double.valueOf(fieldLength).intValue());
                        fi.setNullable(StringUtils.isEmpty(fieldNullable) ? "false":fieldNullable);
                        if(fi.getType().equalsIgnoreCase("Date")){
                            fi.setDataFormat(StringUtils.isEmpty(fieldDataFormat) ? "yyyy-MM-dd hh:mm:ss":fieldDataFormat);
                        }else if((fi.getType().equalsIgnoreCase("Double"))){
                            fi.setDataFormat(StringUtils.isEmpty(fieldDataFormat) ? "#.#######":fieldDataFormat);
                        }else{
                            fi.setDataFormat(StringUtils.isEmpty(fieldDataFormat) ? "":fieldDataFormat);
                        }
                        fi.setEnumValue(StringUtils.isEmpty(fieldEnumValue) ? "":getEnumValueString(fieldEnumValue));
                        fi.setUnique(StringUtils.isEmpty(fieldUnique) ? "":fieldUnique);
                        //for sort
                        oneEntityFieldInfoList.add(fi);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private  static   void write2File(String outputPath,Map<String,Map<String,List<FieldInfo>>> allMap){
        write2File(outputPath,allMap,"","","");
    }
    private  static  void write2File(String outputPath,Map<String,Map<String,List<FieldInfo>>> allMap,String templetPath,String templetPackageName,String templetEntityName){
        if (!(templetPath.endsWith("\\") || templetPath.endsWith("/"))){
            templetPath = templetPath + File.separator;
        }
        for(String wholePackageName:allMap.keySet()){
            Map<String,List<FieldInfo>> onePackageEntityMap = allMap.get(wholePackageName);
            System.out.println("**************************Begin wholePackageName = "+wholePackageName+",entity.size = "+onePackageEntityMap.size()+"*****************************");
            for(String wholeEntityName:onePackageEntityMap.keySet()){
                List<FieldInfo> oneEntityFieldInfoList =  onePackageEntityMap.get(wholeEntityName);
                System.out.println("-------------------Begin wholeEntityName = "+wholeEntityName+",fields.size = "+oneEntityFieldInfoList.size()+"-----------------------");
                for(int i = 0; i < oneEntityFieldInfoList.size(); i++){
                    FieldInfo fn =    oneEntityFieldInfoList .get(i);
                    System.out.println("fieldInfo_"+i+" = "+fn);
                }
                System.out.println("-------------------End wholeEntityName = "+wholeEntityName+",fields.size = "+oneEntityFieldInfoList.size()+"-----------------------");
            }
            System.out.println("**************************End wholePackageName = "+wholePackageName+",entity.size = "+onePackageEntityMap.size()+"*****************************");
        }
        for(String wholePackageName:allMap.keySet()){
            Map<String,List<FieldInfo>> onePackageEntityMap = allMap.get(wholePackageName);
            System.out.println("**************************Begin wholePackageName = "+wholePackageName+",entity.size = "+onePackageEntityMap.size()+"*****************************");
            for(String wholeEntityName:onePackageEntityMap.keySet()){
                List<FieldInfo> oneEntityFieldInfoList =  onePackageEntityMap.get(wholeEntityName);
                System.out.println("-------------------Begin wholeEntityName = "+wholeEntityName+",fields.size = "+oneEntityFieldInfoList.size()+"-----------------------");
                writeOneEntity2File(outputPath,templetPath,templetPackageName,templetEntityName,wholePackageName,wholeEntityName,oneEntityFieldInfoList);
                System.out.println("-------------------End wholeEntityName = "+wholeEntityName+",fields.size = "+oneEntityFieldInfoList.size()+"-----------------------");
            }
            System.out.println("**************************End wholePackageName = "+wholePackageName+",entity.size = "+onePackageEntityMap.size()+"*****************************");
        }
    }

    private static  void writeOneEntity2File(String outputPath,String templetPath,String templetPackageName,String templetEntityName,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        writeEntityClass(outputPath,wholePackageName,wholeEntityName,fieldInfoList);
        if(StringUtils.isEmpty(templetPath) || StringUtils.isEmpty(templetPackageName) || StringUtils.isEmpty(templetEntityName)){
            writeDaoClass(outputPath,wholePackageName,wholeEntityName,fieldInfoList);
            writeServiceClass(outputPath,wholePackageName,wholeEntityName,fieldInfoList);
            writeServiceImplClass(outputPath,wholePackageName,wholeEntityName,fieldInfoList);
        }else{
            writeDaoClass(outputPath,templetPath,templetPackageName,templetEntityName,wholePackageName,wholeEntityName,fieldInfoList);
            writeServiceClass(outputPath,templetPath,templetPackageName,templetEntityName,wholePackageName,wholeEntityName,fieldInfoList);
            writeServiceImplClass(outputPath,templetPath,templetPackageName,templetEntityName,wholePackageName,wholeEntityName,fieldInfoList);
            writeWebClass(outputPath,templetPath,templetPackageName,templetEntityName,wholePackageName,wholeEntityName,fieldInfoList);
        }
    }
    private static void writeWebClass(String outputPath,String templetPath,String templetPackageName,String templetEntityName,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        FileWriter writer;
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        StringBuilder outSB = replaceFileContent(templetPath,templetPackageName,templetEntityName,packageName,entityName,"web","Controller.java");
        writeFile(outputPath, packageName+".web",toUpperCaseFirstOne(entityName.toString())+"Controller",outSB.toString());
    }
    private static void writeServiceImplClass(String outputPath,String templetPath,String templetPackageName,String templetEntityName,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        FileWriter writer;
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        StringBuilder outSB = replaceFileContent(templetPath,templetPackageName,templetEntityName,packageName,entityName,"service"+File.separator +"impl","ServiceImpl.java");
        writeFile(outputPath, packageName+".service.impl",toUpperCaseFirstOne(entityName.toString())+"ServiceImpl",outSB.toString());
    }
    private static  String getEnumValueString(String wholeTarget){
        if(StringUtils.isEmpty(wholeTarget)){
            return  "";
        }
        StringBuilder outSB = new StringBuilder();
        outSB.append("{");
        //枚举值划分
        String tempOne = "";
        String[] wtaReturn = wholeTarget.split("\n");
        for(String one:wtaReturn){
            String[] ov = one.split("=");
            if(ov.length == 2){
                tempOne = ov[0]+("=")+"\\\""+ov[1]+"\\\"";
                if(outSB.indexOf(tempOne) == -1){
                    outSB.append(tempOne).append(",");
                }
            }
        }
        String[] wtaComma  = wholeTarget.split(",");
        for(String one:wtaComma){
            String[] ov = one.split("=");
            if(ov.length == 2){
                tempOne = ov[0]+("=")+"\\\""+ov[1]+"\\\"";
                if(outSB.indexOf(tempOne) == -1){
                    outSB.append(tempOne).append(",");
                }
            }
        }
        outSB.setCharAt(outSB.length() - 1,' ');
        outSB.append("}");
        return outSB.toString();
    }


    private static  String getTargetName(String wholeTarget,int pos){
        wholeTarget = wholeTarget.replace("\r","");
        wholeTarget = wholeTarget.replace(" ","");
        if(StringUtils.isEmpty(wholeTarget)){
            return  null;
        }
        if (pos > 1){
            return null;
        }
        String[] wtaReturn = wholeTarget.split("\n");
        String[] wtaMiddle = wholeTarget.split("-");
        String[] wtaBottom = wholeTarget.split("_");
        if(wtaReturn.length == 2){
            return wtaReturn[pos];
        }
        if(wtaMiddle.length == 2){
            return wtaMiddle[pos];
        }
        if(wtaBottom.length == 2){
            return wtaBottom[pos];
        }
        return wholeTarget;
    }
    private static void writeServiceClass(String outputPath,String templetPath,String templetPackageName,String templetEntityName,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        FileWriter writer;
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        StringBuilder outSB = replaceFileContent(templetPath,templetPackageName,templetEntityName,packageName,entityName,"service","Service.java");
        writeFile(outputPath, packageName+".service",toUpperCaseFirstOne(entityName.toString())+"Service",outSB.toString());
    }
    private static void writeDaoClass(String outputPath,String templetPath,String templetPackageName,String templetEntityName,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        StringBuilder outSB = replaceFileContent(templetPath,templetPackageName,templetEntityName,packageName,entityName,"dao","Repository.java");
        writeFile(outputPath, packageName+".dao",toUpperCaseFirstOne(entityName.toString())+"Repository",outSB.toString());
    }

    private static StringBuilder replaceFileContent(String templetPath,String templetPackageName,String templetEntityName,String packageName,String entityName,String srcFileMiddle,String srcFileTail){
        StringBuilder outSB = new StringBuilder();
        try {
            BufferedReader in = new BufferedReader(new FileReader(templetPath+ srcFileMiddle+File.separator + toUpperCaseFirstOne(templetEntityName)+srcFileTail ));
            String line = "";
            while ((line = in.readLine()) != null) {
                line = line.replace(templetPackageName,packageName);
                line = line.replace(templetEntityName,entityName);
                outSB.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outSB;
    }

    private static String purify(String errChars,String toPurify,boolean containBegin,boolean containEnd,boolean containsMiddle){
        String result = (toPurify == null ? "":toPurify.trim());
        for(int i = 0; i< errChars.length();i++){
            if(containBegin){
                while (result.startsWith(String.valueOf(errChars.charAt(i)))){
                    result = result.substring(1);
                }
            }
            if(containEnd){
                while (result.endsWith(String.valueOf(errChars.charAt(i)))){
                    result = result.substring(1);
                }
            }
            if(containsMiddle){
                result = result.replace(String.valueOf(errChars.charAt(i)),"");
            }
        }
        return result;
    }

    private static boolean isValid(String[] validArray,String value){
        boolean isValid = false;
        for (String validValue:validArray){
            if(validValue.toLowerCase().equals(value.toLowerCase())){
                isValid = true;
                break;
            }
        }
        return isValid;
    }
    private static String purify(String type,Object toPurify){
        String result = (toPurify == null ? "":toPurify.toString().trim());
        String errChars = "\n\r,<.>/?;:'\"[{]}]|()-_=+`~!@#$%^&* ";
        //删除头部尾部所有非法字符
        result = purify(errChars,result,true,true,false);
        //todo
        if ("title".equals(type)){
            result =purify(errChars,result,false,false,true);
        }else if("wholePackageName".equals(type)){
            //除了"."
            result =purify("\r,<>/?;:'\"[{]}]|()=+`~!@#$%^&* ",result,false,false,true);
        }
        else if("wholeEntityName".equals(type)){
            result =purify("\r,<>/?;:'\"[{]}]|()=+`~!@#$%^&* ",result,false,false,true);
        }
        else if("fieldChineseName".equals(type)){
            result =purify("\n\r,./?;:'\"|=+`~!@#$%^&* ",result,false,false,true);
        }
        else if("fieldEnglishName".equals(type)){
            result =purify(errChars,result,false,false,true);
        }
        else if("fieldType".equals(type)){
            result =purify(errChars,result,false,false,true);
            result = toUpperCaseFirstOne(result);
            String[] javaTypeArray = {"byte","short","integer","long","float","double","char","boolean","string"};
            boolean isValid = isValid(javaTypeArray,result);
            if(!isValid){
                result = "";
            }
        }
        else if("fieldLength".equals(type)){
            boolean isValid = true;
            for(int i = 0; i< result.length();i++){
                if(!Character.isDigit(result.charAt(i))){
                    isValid = false;
                }
            }
            if(!isValid){
                result = "";
            }
        }
        else if("fieldNullable".equals(type)
                || "fieldUnique".equals(type)){
            String[] validArray = {"true","false"};
            boolean isValid = isValid(validArray,result);
            if(!isValid){
                result = "";
            }
        }
        else if("fieldDataFormat".equals(type)){
            result =purify("\n\r,<.>/?;:'\"[{]}]|()-_=+`~!@#$%^&* ",result,false,false,true);
            boolean isValid = false;
            if ("yyyy-MM-dd hh:mm:ss".indexOf(result) != -1){
                isValid = true;
            }
            if(!isValid){
                boolean isValidTemp = true;
                for(int i = 0; i< result.length();i++){
                    if(!(result.charAt(i) == '.' || result.charAt(i) == '#') || (result.indexOf(".") != result.lastIndexOf("."))){
                        isValidTemp = false;
                    }
                }
                isValid = isValidTemp;
            }
            if(!isValid){
                result = "";
            }
        }
        else if("fieldEnumValue".equals(type)){
            result =purify("\r<.>/?;:'\"[{]}]|()-_+`~!@#$%^&* ",result,false,false,true);
        }
        return result;
    }

    private static void writeEntityClass(String outputPath,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        String entityChineseName = getTargetName(wholeEntityName,0);
        StringBuilder entityClassFileSB = new StringBuilder();
        entityClassFileSB.append("package "+packageName+".entity;\n");
        entityClassFileSB.append(
                "import com.cpit.platform.common.excel.annotation.ExcelField;\n" )
                .append("import com.cpit.platform.dto.BaseEntity;\n")
                .append("import javax.persistence.*;\n")
                .append("import java.util.Date;\n")
                .append("import java.util.List;\n")
                .append("import com.fasterxml.jackson.annotation.JsonFormat;\n");
        entityClassFileSB.append("@Entity\n" +
                "public class "+ entityName +"  extends BaseEntity {\n");
        entityClassFileSB.append(
                "public static final String ENTITY_DISPLAY_NAME =  \""+ entityChineseName +"\";\n");
        for(int i = 0; i < fieldInfoList.size(); i++){
            FieldInfo fn =   fieldInfoList.get(i);
            if(fn.getType().trim().equalsIgnoreCase("Integer")){
                entityClassFileSB.append("@ExcelField(title= \" ")
                        .append( fn.getChineseName()).append("\", type = ExcelField.TYPE_IMPORT_EXPORT, align= ExcelField.ALIGN_CENTER, sort = 1");
                if(!StringUtils.isEmpty(fn.getEnumValue())){
                    entityClassFileSB.append(",enums=\"") .append(fn.getEnumValue()).append("\"");
                }
                entityClassFileSB.append(")\n");
                entityClassFileSB.append("@Column(nullable = ")
                        .append(fn.getNullable());
                if(!StringUtils.isEmpty(fn.getUnique())){
                    entityClassFileSB.append(",unique =") .append(fn.getUnique());
                }
                entityClassFileSB.append(")\n");
            }else if(fn.getType().trim().equalsIgnoreCase("Double")){
                entityClassFileSB.append("@ExcelField(title= \" ")
                        .append( fn.getChineseName())
                        .append("\", type = ExcelField.TYPE_IMPORT_EXPORT, align= ExcelField.ALIGN_CENTER, sort = 1,fieldType=String.class,decimalFormat = ")
                        .append("\"").append(fn.getDataFormat()).append("\"");
                entityClassFileSB.append(")\n");
                entityClassFileSB.append("@Column(nullable = ").append(fn.getNullable());
                if(!StringUtils.isEmpty(fn.getUnique())){
                    entityClassFileSB.append(",unique =") .append(fn.getUnique());
                }
                entityClassFileSB.append(")\n");
            }else if(fn.getType().trim().equalsIgnoreCase("String")){
                entityClassFileSB.append("@ExcelField(title= \" ").append(fn.getChineseName()).append("\", type = ExcelField.TYPE_IMPORT_EXPORT, align= ExcelField.ALIGN_CENTER, sort = 1");
                if(!StringUtils.isEmpty(fn.getEnumValue())){
                    entityClassFileSB.append(",enums=\"") .append(fn.getEnumValue()).append("\"");
                }
                entityClassFileSB.append(")\n");
                entityClassFileSB.append("@Column(nullable = ").append(fn.getNullable()).append(", length = ").append(fn.getLength());
                if(!StringUtils.isEmpty(fn.getUnique())){
                    entityClassFileSB.append(",unique =") .append(fn.getUnique());
                }
                entityClassFileSB.append(")\n");
            }else if(fn.getType().trim().equalsIgnoreCase("Date")){
                entityClassFileSB.append("@ExcelField(title= \" ").append( fn.getChineseName()).append("\", type = ExcelField.TYPE_IMPORT_EXPORT, align= ExcelField.ALIGN_CENTER, sort = 1,fieldType =Date.class");
                entityClassFileSB.append(")\n");
                entityClassFileSB.append("@JsonFormat(timezone = \"GMT+8\", pattern = ").append("\"").append(fn.getDataFormat()).append("\")\n");
                entityClassFileSB.append("@Column(nullable = ").append(fn.getNullable()).append(", length = ").append(fn.getLength());
                if(!StringUtils.isEmpty(fn.getUnique())){
                    entityClassFileSB.append(",unique =") .append(fn.getUnique());
                }
                entityClassFileSB.append(")\n");
            }
            entityClassFileSB.append("private ").append(fn.getType() ).append(" ").append(fn.getEnglishName()+";\n");

//            entityClassFileSB.append("@Transient\n");
//            String chineseName = fn.getChineseName();
//            String[] chineseNameArray = chineseName.split("-");
//            chineseName = (chineseNameArray.length == 1 ? chineseName : chineseNameArray[1]);
//            entityClassFileSB.append("private String d"+fn.getEnglishName()+" = \""+chineseName+"\";\n");
//            entityClassFileSB.append("\n");
        }
        for(int i = 0; i < fieldInfoList.size(); i++){
            FieldInfo fn =   fieldInfoList.get(i);
            entityClassFileSB.append("public void set")
                    .append(toUpperCaseFirstOne(fn.getEnglishName()))
                    .append("(")
                    .append(fn.getType())
                    .append(" ")
                    .append(fn.getEnglishName())
                    .append("){\n")
                    .append("        this.")
                    .append( fn.getEnglishName())
                    .append(" = ")
                    .append( fn.getEnglishName())
                    .append(";\n")
                    .append("    }\n");

            entityClassFileSB.append("public ").append(fn.getType()).append(" get").append( toUpperCaseFirstOne(fn.getEnglishName())).append( "() {\n" ).append(
                    "        return ").append(fn.getEnglishName()).append(";\n}\n");

//            String englishName = "d"+fn.getEnglishName();
//            entityClassFileSB.append("public void set"+
//                    toUpperCaseFirstOne(englishName) +"(String "+ englishName +"){\n" +
//                    "        this."+ englishName +" = "+ englishName +";\n" +
//                    "    }"+"\n");
//            entityClassFileSB.append("public String get"+ toUpperCaseFirstOne(englishName)+ "() {\n" +
//                    "        return "+englishName+";\n" +
//                    "    }\n");
        }

        entityClassFileSB.append("\npublic String toString() {\n");
        entityClassFileSB.append("return \""+entityName +"{" );
        boolean first = true;
        for(int i = 0; i < fieldInfoList.size(); i++){
            FieldInfo fn =    fieldInfoList.get(i);
            if(first){
                entityClassFileSB.append(fn.getEnglishName()+"=\" + "+fn.getEnglishName()+" + '\\'' +\n");
                first = false;
            }else{
                entityClassFileSB.append("\", "+fn.getEnglishName()+"=\" + "+fn.getEnglishName()+" + '\\'' +\n");
            }
        }
        entityClassFileSB.setCharAt(entityClassFileSB.length() - 2,';');
        entityClassFileSB.append("}\n");
        entityClassFileSB.append("}");
        writeFile(outputPath,packageName+".entity",toUpperCaseFirstOne(entityName.toString())+"",entityClassFileSB.toString());
    }


    private static void writeServiceImplClass(String outputPath,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        String serviceImpl = "package "+packageName+"service.impl;\n" +
                "\n" +
                "import "+packageName+"dao."+entityName+"Repository;\n" +
                "import "+packageName+"entity."+entityName+";\n" +
                "import "+packageName+"service."+entityName+"Service;\n" +
                "import com.cpit.platform.dao.EntityRepository;\n" +
                "import com.cpit.platform.service.impl.EntityServiceImpl;\n" +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import org.springframework.stereotype.Service;\n" +
                "import org.springframework.transaction.annotation.Transactional;\n" +
                "\n" +
                "@Service\n" +
                "@Transactional(rollbackFor = Exception.class)\n" +
                "public class "+entityName+"ServiceImpl extends EntityServiceImpl<"+entityName+"> implements "+entityName+"Service {\n" +
                "    @Autowired\n" +
                "    private "+entityName+"Repository entityRepository;\n" +
                "\n" +
                "    @Override\n" +
                "    protected EntityRepository getEntityRepository() {\n" +
                "        return entityRepository;\n" +
                "    }\n" +
                "}\n";
        writeFile(outputPath,packageName + ".service.impl",toUpperCaseFirstOne(entityName.toString())+"ServiceImpl",serviceImpl);
    }

    private static void writeFile(String outputPath,String relativePath,String fileName,String comment){
        if (!(outputPath.endsWith("\\") || outputPath.endsWith("/"))){
            outputPath = outputPath + File.separator;
        }
        if (relativePath.startsWith(".")){
            relativePath = relativePath.substring(1);
        }
        if (relativePath.endsWith(".")){
            relativePath = relativePath.substring(0,relativePath.length()-1);
        }
        relativePath = relativePath.replace(".",File.separator);
        outputPath = outputPath + relativePath+ File.separator;

        File f = new File(outputPath);
        if(!f.exists()){
            f.mkdirs();
        }

        FileWriter writer;
        try {
            writer = new FileWriter(outputPath+fileName + ".java");
            writer.write(comment);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static void writeServiceClass(String outputPath,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        FileWriter writer;
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);

        String service = "package "+packageName+"service;\n" +
                "\n" +
                "import "+packageName+"entity."+entityName+";\n" +
                "import com.cpit.platform.service.EntityService;\n" +
                "\n" +
                "public interface "+entityName+"Service extends EntityService<"+entityName+"> {\n" +
                "}";
        writeFile(outputPath,packageName+".service",toUpperCaseFirstOne(entityName.toString())+"Service",service);
    }
    private static void writeDaoClass(String outputPath,String wholePackageName,String wholeEntityName,List<FieldInfo> fieldInfoList){
        String packageName = getTargetName(wholePackageName,1);
        String entityName = getTargetName(wholeEntityName,1);
        FileWriter writer;
        String dao =             "package "+packageName+"dao;\n" +
                "\n" +
                "import "+packageName+"entity."+entityName+";\n" +
                "import com.cpit.platform.dao.EntityRepository;\n" +
                "import org.springframework.stereotype.Component;\n" +
                "\n" +
                "@Component\n" +
                "public interface "+entityName+"Repository extends EntityRepository<"+entityName+"> {\n" +
                "}\n";
        writeFile(outputPath,packageName+".dao",toUpperCaseFirstOne(entityName.toString())+"Repository",dao);

    }

    private static Date strToDate(String str) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        try {
            date = format.parse(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

    //首字母转小写
    private static String toLowerCaseFirstOne(String s){
        if(StringUtils.isEmpty(s)){
            return s;
        }
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return Character.toLowerCase(s.charAt(0))+s.substring(1);
    }
    //首字母转大写
    private static String toUpperCaseFirstOne(String s){
        if(StringUtils.isEmpty(s)){
            return s;
        }
        if(Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return Character.toUpperCase(s.charAt(0))+ s.substring(1);
    }

    //获取单元格各类型值，返回字符串类型
    private static String getCellFormatValue(Cell cell) {

        //判断是否为null或空串
        if (cell==null || cell.toString().trim().equals("")) {
            return "";
        }
        //evaluator=wb.getCreationHelper().createFormulaEvaluator();
        String cellValue = "";
        int cellType=cell.getCellType();

        if(cellType==Cell.CELL_TYPE_FORMULA){ //表达式类型
           // cellType=evaluator.evaluate(cell).getCellType();
        }
        try{
            switch (cellType) {
                case Cell.CELL_TYPE_STRING: //字符串类型
                    cellValue= cell.getRichStringCellValue().getString();
                    cellValue=StringUtils.isEmpty(cellValue) ? "" : cellValue;
                    break;
                case Cell.CELL_TYPE_BOOLEAN:  //布尔类型
                    cellValue = String.valueOf(cell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC: //数值类型
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {  //判断日期类型
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        cellValue =  format.format(cell.getDateCellValue());
                    } else {  //否
                        cellValue = new DecimalFormat("#.######").format(cell.getNumericCellValue());
                    }
                    break;
                case Cell.CELL_TYPE_FORMULA: // 公式
                    cellValue = cell.getCellFormula() + "";
                    break;
                case Cell.CELL_TYPE_BLANK:
                    cellValue = "";;
                    break;
                case Cell.CELL_TYPE_ERROR:
                    cellValue = "非法字符";;
                    break;
                default: //其它类型，取空串吧
                    cellValue = "";
                    break;
            }
        }catch (Exception e){
            System.out.println("[In getCellFormatValue]catch exception,row = "+cell.getRowIndex()+",column="+cell.getColumnIndex());
            e.printStackTrace();
        }
        return cellValue;
    }
    public static void generatorFile(String entityFilePath,String outputPath,String templetPath,String templetPackageName,String templetEntityName){
        Map<String,Map<String,List<FieldInfo>>> allEntityMap = null;
        try{
            allEntityMap = FileGenerator.readData(entityFilePath);
        } catch (FileNotFoundException e) {
            System.out.println("未找到指定路径的文件!");
            e.printStackTrace();
            return;
        }catch (Exception e) {
            e.printStackTrace();
            return;
        }
        if(StringUtils.isEmpty(templetPath ) || StringUtils.isEmpty(templetPackageName ) || StringUtils.isEmpty(templetEntityName )){
            URL url = FileGenerator.class.getClassLoader().getResource("./");
            String newTempletPath = "";
            String newTempletPackageName = "com.cpit.platform.tool.templet";
            String newTempletEntityName = "TempletEntity";
            if(url != null){
                String curPath = url.getPath();
                String[] pathArray = curPath.split("/");
                for(int i = 0; i < pathArray.length - 2; i++){
                    newTempletPath = newTempletPath + pathArray[i] + File.separator;
                }
                newTempletPath = newTempletPath + "src/main/java/com/cpit/platform/tool/templet";
                templetPath =newTempletPath;
                templetPackageName = newTempletPackageName ;
                templetEntityName =newTempletEntityName;
            }
        }
        if(StringUtils.isEmpty(templetPath ) || StringUtils.isEmpty(templetPackageName ) || StringUtils.isEmpty(templetEntityName )){

        }else{
            FileGenerator.write2File(outputPath,allEntityMap,templetPath,templetPackageName,templetEntityName);
        }
    }

    public static void main(String[] args) {
        try {
//            String entityFilePath = "D:\\work\\IntelliJProj\\Project\\IntegrationPlatform\\doc\\模型需求定义模板.xlsx";
            URL url = FileGenerator.class.getClassLoader().getResource("./");
            String entityFilePath = "";
            if(url != null){
                String curPath = url.getPath();
                String[] pathArray = curPath.split("/");
                for(int i = 0; i < pathArray.length - 2; i++){
                    entityFilePath = entityFilePath + pathArray[i] + File.separator;
                }
                entityFilePath = entityFilePath + "doc/模型需求定义模板.xlsx";
            }
            FileGenerator.generatorFile(entityFilePath,"d:\\my","","","");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}